package com.huohua.jobschduler.JobProcess;

import com.huohua.jobschduler.model.po.IJob;
import com.huohua.jobschduler.model.po.JobNode;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

public abstract class AsyncDependencyResolver extends DependencyResolver {

    private final ThreadPoolExecutor executorService;

    private static final int threadPoolSize = 16;

    private static final int queueSize = 1;



    public AsyncDependencyResolver() {
        // 创建固定大小的线程池
        this.executorService = new ThreadPoolExecutor(
                threadPoolSize,
                threadPoolSize,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(queueSize)
        );
    }

    public JobNode findErrorPaths(String jobId) {
        IJob job = getJob(jobId);
        if(job == null) {
            return null;
        }
        if (job.isSuccess()) {
            return new JobNode(job);
        }

        JobNode jobNode = null;
        try {
            jobNode= dfsErrorPaths(job, new LinkedHashSet<>(), new ConcurrentHashMap<>());
        } catch (ExecutionException | InterruptedException e) {
                throw new RuntimeException(e);
        }
        return jobNode;
    }
    // 多线程 DFS 方法
    private JobNode dfsErrorPaths(IJob job, LinkedHashSet<String> visited, Map<String, JobNode> idToNode) throws InterruptedException, ExecutionException {
        // 检测循环依赖
        if (job.in(visited)) {
            String[] visitedArr = visited.toArray(new String[0]);
            // 将末尾到环起始点的Job都设置环标识符isRing
            for (int i = visitedArr.length - 1; i >= 0; i--) {
                idToNode.get(visitedArr[i]).setIsRing(true);
                if (job.equalsJobId(visitedArr[i])) {
                    break;
                }
            }
            return new JobNode(job);
        }

        // 标记当前作业为已访问
        visited.add(job.uniqueId());

        JobNode jobNode = new JobNode(job);
        idToNode.put(job.uniqueId(), jobNode);

        if (job == null) {
            // 作业不存在，终止递归，回溯并移除当前作业
            visited.remove(job.uniqueId());
            return null;
        }

        // 如果作业状态为 FAIL，回溯并返回当前 JobNode
        if (job.isFail()) {
            visited.remove(job.uniqueId());
            return jobNode;
        }

        // 如果作业状态为 UNPROCESSED，使用多线程处理前置依赖
        if (job.isUnprocessed()) {
            // 获取当前作业的前置依赖作业
            List<IJob> preJobs = getPreJobs(job);

            // 创建一个存储 Future 的列表，用于保存异步任务
            List<Future<JobNode>> futures = new ArrayList<>();

            for (IJob preJob : preJobs) {
                // 将当前线程的 visited 状态传递给子线程
                if (preJobs.size() == 1 || executorService.getActiveCount()>=executorService.getCorePoolSize()) {
                    jobNode.addPreJobNode(dfsErrorPaths(preJob, visited, idToNode));
                } else {
                    LinkedHashSet<String> parentVisited = new LinkedHashSet<>(visited); // 拷贝当前的 visited 集合
                   try{
                       Future<JobNode> future = executorService.submit(() -> {
                           try {
                               // 在子线程中传递父线程的 visited 集合
                               return dfsErrorPaths(preJob, parentVisited, idToNode);
                           } catch (Exception e) {
                               throw new RuntimeException(e);
                           }
                       });
                       futures.add(future);
                   }catch (RejectedExecutionException e){
                       jobNode.addPreJobNode(dfsErrorPaths(preJob, visited, idToNode));
                   }
                }
            }

            // 收集每个 Future 的执行结果
            for (Future<JobNode> future : futures) {
                JobNode preJobNode = future.get();  // 等待并获取每个异步任务的结果
                if (preJobNode != null) {
                    jobNode.addPreJobNode(preJobNode);
                }
            }

            // 回溯：递归完成后移除当前作业
            visited.remove(job.uniqueId());
            return jobNode;
        }

        // 回溯：递归完成后移除当前作业
        visited.remove(job.uniqueId());
        return null;  // 如果作业状态正常，返回 null
    }



    // 关闭线程池
    public void shutdown() {
        executorService.shutdown();
    }

    // 获取作业信息的抽象方法，实际应用中替换为数据库查询
    protected abstract IJob getJob(String jobId);


    protected abstract List<IJob> getPreJobs(IJob job);
}

